/*===================================================================

以下是滑动平均处理的相关代码，

===================================================================*/

#include "movemean.h"
#include "stdbool.h"
#include "string.h"


/**
 * @brief     : 判断缓冲区是否填满
 * @param[in] : Wismed_Movmean_Manager_t *manager 判断的缓冲区结构体； int filterLen 对比的长度
 * @return    : 逻辑值
 * @readme    : 
 * @author    : liuyue
 * @date      : 20221110
 */
bool vismedMovmeanInitCompleted(Wismed_Movmean_Manager_t *manager, int filterLen) {
	if (manager == NULL)
        return false;
	if (manager->nDealDataCnt >= filterLen)
		return true;
	else 
		return false;
}

/**
 * @brief     : 做滑动平均的结构体变量初始化
 * @param[in] : Wismed_Movmean_Manager_t *manager 缓冲区结构体
 * @return    : void
 * @readme    : 
 * @author    : liuyue
 * @date      : 20221110
 */
void wismed_movean_init(Wismed_Movmean_Manager_t *manager) {
    if (manager == NULL)
        return;
	if (manager->nBufLen > 0 && manager->fMovMeanBuf != NULL)
		memset(manager->fMovMeanBuf, 0, sizeof(float) * manager->nBufLen);
    manager->nMovMeanIndex = 0;
    manager->dMovmeanSum = 0;
	if (manager->nBufLen > 0 && manager->fMovMeanDiffBuf != NULL)
		memset(manager->fMovMeanDiffBuf, 0, sizeof(float) * manager->nBufLen);
    manager->dMovMeanDiffsum = 0;
    manager->nDealDataCnt = 0;
}

/**
 * @brief     : 滑动平均处理函数
 * @param[in] : float datain 用于做滑动平均的入数据; int window 滑动平均的窗口大小; 
				int mode 滤波模式 是否需要延时; Wismed_Movmean_Manager_t *manager 缓冲区结构体
 * @return    : float 滤波后数据输出
 * @readme    : 
 * @author    : liuyue
 * @date      : 20221110
 */
float wismed_movmean(float datain, int window, int mode, Wismed_Movmean_Manager_t *manager) {
    if (manager == NULL || manager->nBufLen <= 0 || manager->fMovMeanBuf == NULL)
        return 0;
    if (window < 0 || window > manager->nBufLen)
        window = manager->nBufLen;
    int filterLen = window;

    //删除旧数据,添加新数据
    manager->dMovmeanSum -= manager->fMovMeanBuf[manager->nMovMeanIndex];
    manager->fMovMeanBuf[manager->nMovMeanIndex] = datain;
    manager->dMovmeanSum += manager->fMovMeanBuf[manager->nMovMeanIndex];

    if (mode == Wismed_Movmean_Work_NoDelay && manager->fMovMeanDiffBuf != NULL) {
        //将延时拉下来
        manager->dMovMeanDiffsum -= manager->fMovMeanDiffBuf[manager->nMovMeanIndex];
        if (manager->nDealDataCnt == 0)
        {
            //首个点的差分为0
            manager->fMovMeanDiffBuf[manager->nMovMeanIndex] = 0;
        }
        else
        {
            //求上一个值减去当前值的差
            if (manager->nMovMeanIndex == 0)
                manager->fMovMeanDiffBuf[manager->nMovMeanIndex] = manager->fMovMeanBuf[filterLen-1] - manager->fMovMeanBuf[manager->nMovMeanIndex];
            else
                manager->fMovMeanDiffBuf[manager->nMovMeanIndex] = manager->fMovMeanBuf[manager->nMovMeanIndex-1] - manager->fMovMeanBuf[manager->nMovMeanIndex];
        }
        manager->dMovMeanDiffsum += manager->fMovMeanDiffBuf[manager->nMovMeanIndex];
        //将延时拉下来
    }

    manager->nMovMeanIndex++;
    if (manager->nMovMeanIndex >= filterLen)
        manager->nMovMeanIndex = 0;


    if (manager->nDealDataCnt >= filterLen)
    {
        if (mode == Wismed_Movmean_Work_NoDelay)
            return manager->dMovmeanSum / filterLen - manager->dMovMeanDiffsum / 2.0;
        else
            return manager->dMovmeanSum / filterLen;
    }
    else
    {
        manager->nDealDataCnt++;
        return datain;
    }
}


/*********************举例说明************************/
/*
// 滑动平均滤波器(用于去除实时压噪声)
float fMmovMeanPressureBuf[3];
Wismed_Movmean_Manager_t movMeanPressure = {
	.nBufLen = 3,
	.fMovMeanBuf = fMmovMeanPressureBuf,
	.fMovMeanDiffBuf = NULL
};

// 初始化实时压力滤波器
wismed_movean_init(&movMeanPressure);

float pressure_remove_noise = wismed_movmean(dataIn, 3, Wismed_Movmean_Work_Normal, &movMeanPressure);
*/

/*===================================================================

以上是滑动平均处理的相关代码，

===================================================================*/

